package cn.yangliu.nacos.management.service.sys.impl;

import java.util.List;
import java.util.Optional;

import static cn.yangliu.nacos.management.constant.CacheConstants.AUTHORITY_CACHE;

import cn.yangliu.jpa.base.service.impl.JpaServiceImpl;
import cn.yangliu.nacos.comm.enums.GlobalResultCode;
import cn.yangliu.nacos.comm.ex.GlobalException;
import cn.yangliu.nacos.management.entity.sys.Authority;
import cn.yangliu.nacos.management.entity.sys.Role;
import cn.yangliu.nacos.management.model.RoleInsertModel;
import cn.yangliu.nacos.management.model.RoleUpdateModel;
import cn.yangliu.nacos.management.repository.sys.AuthorityRepository;
import cn.yangliu.nacos.management.repository.sys.Role2AuthorityRepository;
import cn.yangliu.nacos.management.repository.sys.RoleRepository;
import cn.yangliu.nacos.management.repository.sys.User2RoleRepository;
import cn.yangliu.nacos.management.service.sys.RoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * The type of nacos.
 *
 * @author 问道于盲
 * @date 2020 -01-01
 */
@Service
@Transactional(rollbackFor = Throwable.class)
public class RoleServiceImpl extends JpaServiceImpl<Role, Long, RoleRepository> implements RoleService {

    /**
     * current class instance's member.
     * The Authority repository.
     */
    @Autowired
    private AuthorityRepository authorityRepository;

    /**
     * current class instance's member.
     * The User 2 role repository.
     */
    @Autowired
    private User2RoleRepository user2RoleRepository;

    /**
     * current class instance's member.
     * The Role 2 authority repository.
     */
    @Autowired
    private Role2AuthorityRepository role2AuthorityRepository;

    /**
     * Insert role.
     *
     * @param model the model
     * @return the role
     */
    @Override
    @CacheEvict(cacheNames = AUTHORITY_CACHE, allEntries = true)
    public Role insert(RoleInsertModel model) {
        Role role = new Role();
        BeanUtils.copyProperties(model,role);
        storeAuthorities(role, model.getAuthorityIds());
        return repository.save(role);
    }

    /**
     * Update role.
     *
     * @param model the model
     * @return the role
     */
    @Override
    @CacheEvict(cacheNames = AUTHORITY_CACHE, allEntries = true)
    public Role update(RoleUpdateModel model) {
        Optional<Role> optional = repository.findById(model.getId());
        if (!optional.isPresent()) {
            throw new GlobalException(GlobalResultCode.DATA_NOT_EXIST);
        }
        Role role = optional.get();
        storeAuthorities(role, model.getAuthorityIds());
        return repository.save(role);
    }

    /**
     * Store authorities.
     *
     * @param role         the role
     * @param authorityIds the authority ids
     */
    private void storeAuthorities(Role role, List<Long> authorityIds) {
        if (CollectionUtils.isEmpty(authorityIds)){
            return;
        }
        List<Authority> authorities = authorityRepository.findAllById(authorityIds);
        role.setAuthorities(authorities);
    }

    /**
     * Delete by id.
     *
     * @param id the id
     */
    @Override
    @CacheEvict(cacheNames = AUTHORITY_CACHE, allEntries = true)
    public void deleteById(Long id) {

        user2RoleRepository.deleteByRoleId(id);

        role2AuthorityRepository.deleteByRoleId(id);

        repository.deleteById(id);
    }
}
